/*
Marcus Ruether
4-20-08
Desc: runs virtual machine
*/

#include<stdio.h>
#include<string.h>
#include"lexar.h"

int main(int argc, char *argv[])
{
	//take sourceCode as command line arg

	FILE *SOURCE;
	if(!(SOURCE = fopen(argv[1], "r")))
	{
		fprintf(stderr, "Source file specified on command line does not exit\nExiting Virtual Machine");
		exit(1);
	}
	
	char line[500];
	int numbOfOps;
	numbOfOps = 0;
	while(fgets(line, 500, SOURCE))
	{
		++numbOfOps;
	}

	fprintf(stderr,"Number if Operations: %d\n", numbOfOps);
	
	struct tokenList *Operations = malloc(sizeof(struct tokenList)*(numbOfOps));
	fclose(SOURCE);
	SOURCE = fopen(argv[1], "r");

	//tokenize inputs
	lex_main(SOURCE, stdout, stderr, Operations, numbOfOps);
	//operations are now stored in Operations[] as tokens
	//can close SOURCE file
	fclose(SOURCE);

	//we now have all operations in an array of tokenList
	struct vm//stores current oparations number(IP) and all register values
	{
		int reg[8]; 
		int IP;
	};
	struct vm vmState;
	//initial values of vm
	int k = 0;
	//initializes register of vmState
	for(k; k < 8;++k)
	{
		vmState.reg[k] = 0;
	}
	vmState.IP = 0;

//crap for debugging
	k = 0;
	struct token *testTok;
	for(k; k < numbOfOps; k++)
	{
		fprintf(stderr,"OPERATION %d ------------------------------------\n", k+1);
		testTok = Operations[k].head;
		while(testTok != NULL)
		{
			fprintf(stderr,"%s\n",&testTok->strVal);
			testTok = testTok->next;
		}
	}
	
	while(vmState.IP < numbOfOps)
	{
		struct token *cmdToken;
		//up to four arguments, I dont think we will need more than that
		struct token *arg1;
		struct token *arg2;
		struct token *arg3;

		cmdToken = Operations[vmState.IP].head;
		//all the if/else switches to determine the operation to take
		
		if(cmdToken == NULL)
		{
			++vmState.IP;
			fprintf(stderr,"blank line\n");
			continue;
		}
		else if(cmdToken->type == JUNK)
		{
			fprintf(stderr,"Invalid Operation at line number: %d\n", cmdToken->lineNumb);
		}
		else if(cmdToken->type == COMMENT)
		{
			++vmState.IP;
			fprintf(stderr,"comment\n");
			continue;
		}
		else//at this point we can assume this first command token is a valid operation
		{
			//if cmdToken->head is MOV and the next token is not null
			if( (cmdToken->type == OPCODE) && (cmdToken->v.op == MOV) && (cmdToken->next != NULL) )
			{
				cmdToken = cmdToken->next;
				arg1 = cmdToken;
				//if second token is is register and next token is not null
				if( (cmdToken->type == REGI) && (cmdToken->next != NULL))
				{
					cmdToken = cmdToken->next;
					arg2 = cmdToken;
					//if last token is register
					if(cmdToken->type == REGI)
					{	//args are vm, second token in list, and third token in list
						vmState.reg[arg1->v.r] = vmState.reg[arg2->v.r];
						fprintf(stdout,"MOVING REG INTO REG\n");
					}
					//if last token is int
					else if(cmdToken->type == INTEGER)
					{
						vmState.reg[arg1->v.r] = arg2->v.i;
						fprintf(stdout,"MOVING INT INTO REGI\n");
					}
					else
					{
						fprintf(stderr,"Invalid argument(s) on line number: %d\n", cmdToken->lineNumb);
					}
				}
				else
				{
					fprintf(stderr,"Invalid aregument(s) on line number: %d\n", cmdToken->lineNumb);
				}
			}
			else
			{			
				fprintf(stderr,"Invalid Operation on line number: %d\n", cmdToken->lineNumb);
			}		
			//repeat what I did with MOV for the rest of the operations...
			//this is going to be alot of repeatitive codei
		}
		vmState.IP++;
	}
	

	k=0;
	for(k; k < numbOfOps; k++)
	{
		fprintf(stderr,"deleting operation %d\n", (k+1));
		delete_tokenList(&Operations[k]);
	}

}
